﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using System.IO;

namespace SmartText.Converter
{
    class XMLToLua
    {
        private const string SRC_START =
            "{0} = ";
        private const string SRC_ELEMENT_START =
            "['{0}'] = ";
        private const string SRC_BRACE_START =
            "{";
        private const string SRC_BRACE_END =
            "}";
        private const string SRC_CONTENT =
            "['{0}'] = {1},";

        public static string ConvertToLua(string sFileName, Encoding enc)
        {
            using (var sr = new StreamReader(sFileName, enc))
            {
                var sbLua = new StringBuilder();
                var xe = XDocument.Load(sr).Root;

                sbLua.AppendLine(string.Format(SRC_START, xe.Name.LocalName));
                sbLua.AppendLine(SRC_BRACE_START);
                sbLua.Append(ParseChildToLua(xe, 0));
                sbLua.AppendLine(SRC_BRACE_END);
                return sbLua.ToString();
            }
        }

        private static string ParseChildToLua(XElement xe, int indent)
        {
            var sbLua = new StringBuilder();
            var set = new HashSet<string>();

            foreach (var att in xe.Attributes())
            {
                sbLua.AppendLine(Indent(indent + 4) + string.Format(SRC_CONTENT, att.Name.LocalName, GetValue(att.Value)));
            }
            foreach (var element in xe.Elements())
            {
                if (set.Contains(element.Name.LocalName))
                {
                    continue;
                }

                if (xe.Elements(element.Name).Count() > 1)
                {
                    sbLua.AppendLine(Indent(indent + 4) + string.Format(SRC_ELEMENT_START, element.Name.LocalName));
                    sbLua.AppendLine(Indent(indent + 4) + SRC_BRACE_START);
                    foreach (var e in xe.Elements(element.Name))
                    {
                        if (e.HasElements || e.HasAttributes)
                        {
                            sbLua.AppendLine(Indent(indent + 8) + SRC_BRACE_START);
                            sbLua.Append(ParseChildToLua(e, indent + 8));
                            sbLua.AppendLine(Indent(indent + 8) + SRC_BRACE_END + ",");
                        }
                        else if (e.Value != null)
                        {
                            sbLua.AppendLine(Indent(indent + 8) + GetValue(e.Value) + ",");
                        }
                    }
                    sbLua.AppendLine(Indent(indent + 4) + SRC_BRACE_END + ",");
                    set.Add(element.Name.LocalName);
                }
                else
                {
                    if (element.HasElements || element.HasAttributes)
                    {
                        sbLua.AppendLine(Indent(indent + 4) + string.Format(SRC_ELEMENT_START, element.Name.LocalName));
                        sbLua.AppendLine(Indent(indent + 4) + SRC_BRACE_START);
                        sbLua.Append(ParseChildToLua(element, indent + 4));
                        sbLua.AppendLine(Indent(indent + 4) + SRC_BRACE_END + ",");
                    }
                    else if (element.Value != null)
                    {
                        sbLua.AppendLine(Indent(indent + 4) + string.Format(SRC_CONTENT, element.Name.LocalName, GetValue(element.Value)));
                    }
                }
            }

            return sbLua.ToString();
        }

        private static string Indent(int count)
        {
            return new String(' ', count);
        }

        private static string GetValue(string value)
        {
            double dNum;
            if (Double.TryParse(value, out dNum))
            {
                return value; ;
            }
            else
            {
                return "'" + value + "'";
            }
        }
    }


}
